/*
 * Copyright 2008 Max Kugland
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.splink.library.queue {

	/**
	 * Interface for <code>IQ</code> implementations which can asyncrously process 
	 * <code>IQ</code> and <code>IQable</code> implementations.
	 * 
	 * Basically you can add <code>IQable</code> implementations to an <code>IQ</code> and 
	 * the <code>IQ</code> processes the added items in the order they have been added. The
	 * <code>IQ</code> also checks if an added <code>IQable</code> is also an <code>IQ</code>
	 * (this is possible, because <code>IQ</code> inherits from <code>IQable</code>). If
	 * that is true, the content of the <code>IQ</code> gets processed to. This enables you to
	 * build tree-like structures of asyncronous operations.
	 * Once an operation completes the <code>IQable</code> notifies the <code>IQ</code>
	 * and the <code>IQ</code> proceeds with the next item.
	 * 
	 * Just before the an <code>IQable</code> starts it fires and <code>QEvent.START</code>,
	 * while the <code>IQable</code> processes it fires <code>QEvent.PROGRESS</code>.
	 * Upon completion an  <code>QEvent.COMPLETE</code> is fired.
	 * 
	 * @see org.splink.library.queue.QEvent
	 * @see org.splink.library.queue.IQable
	 * @author Max Kugland
	 */
	public interface IQ extends IQable {
		
		/**
		 * Adds an <code>IQable</code> item to the <code>IQ</code>. As <code>IQ</code> extends
		 * <code>IQable</code> <code>IQ</code> implementation can also be added to an 
		 * <code>IQ</code> (Composite).
		 * 
		 * @param item add an <code>IQable</code> item to the <code>IQ</code>
		 * @return the added <code>IQable</code> item
		 * @see org.splink.library.queue.IQable
		 */
		function add(item : IQable) : IQable;

		/**
		 * Removes an item from the <code>IQ</code>. If the item is currently in use, the 
		 * <code>IQ</code> stops processing the item and proceeds to the next item.
		 * The <code>IQable</code> must be firsthand part of this <code>IQ</code>. 
		 * 
		 * @param item the item to be removed from the <code>IQ</code>
		 * @return the given <code>IQable</code>
		 * @see org.splink.library.queue.IQable
		 */
		function remove(item : IQable) : IQable;

		/**
		 * Returns the item which belongs to the given id if it is firsthand 
		 * part of the <code>IQ</code>, otherwise returns null
		 * 
		 * @param item the id of the item to return
		 * @return the item which belongs to the specified id
		 * 
		 * @see org.splink.library.queue.IQable
		 */
		function getForId(id : String) : IQable;

		/**
		 * Enables to iterate the enqueued <code>IQable</code> via
		 * @example
		 * <listing version="3.0"> for (var i : int = 0;i < q.count;i++) { var qable : IQable = q.getAt(i); }
		 * 
		 * @param index the index of the <code>IQable</code> to return
		 * @return the <code>IQable</code> at to given index
		 */
		function getAt(index : uint) : IQable;

		/**
		 * Returns the currently processing <code>IQable</code> from the enclosing <code>IQ</code>
		 * point of view. So only <code>IQable</code>s which are direct members of the
		 * <code>IQ</code> are returned.
		 * If no <code>IQable</code> can be found,  null is returned instead.
		 * 
		 * @return the currently processing <code>IQable</code> item 
		 */
		function get current() : IQable;

		/**
		 * @return the number of items which have been added to this <code>IQ</code>
		 */
		function get length() : int;

		/**
		 * @return whether the <code>IQ</code> is currently running
		 */
		function get isRunning() : Boolean;
	}
}
